/**
 * Copyright 2019 吉鼎科技.

 * <p>
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * <p>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package cn.easyplatform.type;

import cn.easyplatform.castor.Castors;
import cn.easyplatform.lang.Mirror;
import cn.easyplatform.lang.Nums;

import java.util.Date;

/**
 * @author <a href="mailto:davidchen@epclouds.com">littleDog</a> <br/>
 * @since 2.0.0 <br/>
 */
public enum FieldType {

	/**
	 * 字符
	 */
	CHAR,

	/**
	 * 布尔值
	 */
	BOOLEAN,

	/**
	 * 字符串
	 */
	VARCHAR,

	/**
	 * 字符大对象
	 */
	CLOB,

	/**
	 * 二进制大对象
	 */
	BLOB,

	/**
	 * 带时间的日期
	 */
	DATETIME,

	/**
	 * 日期
	 */
	DATE,

	/**
	 * 时间
	 */
	TIME,

	/**
	 * 整型,可定义长度
	 */
	INT,

	/**
	 * 长整型
	 */
	LONG,

	/**
	 * 带小数位的数字
	 */
	NUMERIC,

	/**
	 * JAVA对象
	 */
	OBJECT;

	/**
	 * @param type
	 * @return
	 */
	public final static FieldType getType(String name) {
		for (FieldType type : FieldType.values()) {
			if (type.toString().equalsIgnoreCase(name))
				return type;
		}
		return null;
	}

	public final static FieldType cast(Object v) {
		if (v == null)
			return FieldType.OBJECT;
		Class<?> clazz = v.getClass();
		if (clazz.isPrimitive()) {
			if (clazz == int.class || clazz == short.class
					|| clazz == byte.class)
				return FieldType.INT;
			if (clazz == long.class)
				return FieldType.LONG;
			if (clazz == double.class || clazz == float.class)
				return FieldType.NUMERIC;
			if (clazz == boolean.class)
				return FieldType.BOOLEAN;
			if (clazz == char.class)
				return FieldType.CHAR;
		}
		if (v instanceof Integer)
			return FieldType.INT;
		if (v instanceof Long)
			return FieldType.LONG;
		if (v instanceof CharSequence)
			return FieldType.VARCHAR;
		if (v instanceof Date)
			return FieldType.DATETIME;
		if (v instanceof Number)
			return FieldType.NUMERIC;
		if (v instanceof byte[])
			return FieldType.BLOB;
		if (v instanceof Boolean)
			return FieldType.BOOLEAN;
		if (v instanceof Character)
			return FieldType.CHAR;
		if (clazz.getSimpleName().equals("FieldDo")) {
			try {
				return (FieldType) Mirror.me(clazz)
						.getInvoking("getType", (Object) null).invoke(v);
			} catch (Exception ex) {
			}
		}
		return FieldType.OBJECT;
	}

	public static Object cast(Object obj, FieldType type) {
		if (obj == null)
			return null;
		switch (type) {
		case CHAR:
		case VARCHAR:
		case CLOB:
			if (obj instanceof String)
				return (String) obj;
			else
				return obj.toString();
		case LONG:
			if (obj instanceof Long)
				return obj;
			if (obj instanceof Number) {
				Number num = (Number) obj;
				return num.longValue();
			} else {
				return Nums.toLong(obj.toString(), 0);
			}
		case INT:
			if (obj instanceof Integer)
				return obj;
			if (obj instanceof Number) {
				Number num = (Number) obj;
				return num.intValue();
			} else {
				return Nums.toInt(obj.toString(), 0);
			}
		case TIME:
		case DATE:
		case DATETIME:
			if (obj instanceof Date)
				return obj;
			else if(obj instanceof Number)
				return new Date(((Number)obj).longValue());
			else
				return Castors.me().castTo(obj, Date.class);
		case BOOLEAN:
			if (obj instanceof Boolean)
				return obj;
			if (obj instanceof Number) {
				Number num = (Number) obj;
				if (num.intValue() > 0)
					return true;
				else
					return false;
			}
			if (obj instanceof String) {
				String s = obj.toString();
				return s.equalsIgnoreCase("true");
			}
		case NUMERIC:
			if (obj instanceof Double)
				return obj;
			if (obj instanceof Number)
				return ((Number) obj).doubleValue();
			else if (!obj.toString().trim().equals(""))
				return Double.parseDouble(obj.toString());
		default:
			return obj;
		}
	}
}
